package com.bsmyl.lottery.Service.impl;

import com.alibaba.fastjson.JSON;
import com.bsmyl.lottery.Service.PlanService;
import com.bsmyl.lottery.config.LotteryConfig;
import com.bsmyl.lottery.core.MapUtile;
import com.bsmyl.lottery.core.SimulationPlanConfig;
import com.bsmyl.lottery.dao.LotteryDao;
import com.bsmyl.lottery.dao.PkDetailDao;
import com.bsmyl.lottery.dao.PkPlanModelDao;
import com.bsmyl.lottery.feign.LotteryFeignClient;
import com.bsmyl.lottery.model.*;
import com.bsmyl.lottery.play.PlayController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * describe:
 *
 * @author LiuWenPing
 * @date 2019/02/21
 */
@Service
public class PlanServiceImpl implements PlanService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PlanServiceImpl.class);

    //private static boolean isGent

    @Autowired
    private PkDetailDao pkDetailDao;

    @Autowired
    private LotteryDao lotteryDao;

    @Autowired
    private PkPlanModelDao pkPlanModelDao;


    @Autowired
    private LotteryFeignClient lotteryFeignClient;


    private final Long LOTTERY_ID = 1025L;
    private Integer NUM_SIZE = 20;

    private Lottery prveLottery = null;

    @Override
    public void plan(){
        /*LotteryInfoParam lotteryInfoParam = new LotteryInfoParam(IssueServiceImpl.token, 1025, 1);
        Result result = lotteryFeignClient.LotteryHistoryOpenInfo(JSON.toJSONString(lotteryInfoParam));
        if (result.getData().getHistoryList() == null) {
            return;
        }*/
        //查找最新的结果
        //Lottery lottery = result.getData().getHistoryList().get(0);
        Lottery lottery =SimulationPlanServiceImpl.getLottery(); //lotteryDao.getQQLottery();

        Lottery localLottery = lotteryDao.getLottery(1025L, lottery.getIssue());
        if (prveLottery != null&&lottery.getIssue().equals(prveLottery.getIssue()) ) {//说明还是本期,没有开出下一期来.
            return;
        }
        //开了新的一期
        if (localLottery==null||localLottery.getIssue()==null
                ||!localLottery.getIssue().equals(lottery.getIssue())) {//如果数据库将新的数据添加进去了.则 查到的期号和新开的期号是一样的.则说明数据已经存进数据了,否则重来.
            return;
        }
        //String[] openNums = lottery.getOpenNum().split(",");
        String[] openNums = lottery.getOpenNum().split(",");
        System.out.println(JSON.toJSONString(openNums));
        for (int i = 0; i < openNums.length; i++) {
            PkPlanModel prevPkPlanModel = LotteryConfig.pkPlanModels[i + 1];
            if (prevPkPlanModel != null && prevPkPlanModel.getIssue().equals(lottery.getIssue())) {
                boolean isWin = false;
                for (int j = 0; j < prevPkPlanModel.getBetNums().length; j++) {
                    if (Integer.valueOf(openNums[i]).equals(prevPkPlanModel.getBetNums()[j])) {
                        isWin = true;
                        break;
                    }
                }
                //倍投倍率增加、止损策略
                if (!isWin) {//输了
                    LotteryConfig.pkLoseCount[prevPkPlanModel.getRanking()]++;
                    //超过5局停止下注
                } else {
                    LotteryConfig.pkLoseCount[prevPkPlanModel.getRanking()] = 0;
                    LotteryConfig.stopLoss = false;  //赢了转换为不止损.
                }
                if (SimulationPlanConfig.isStart) {
                    if (SimulationPlanConfig.isAllowBet) {//达到策略下注要求,计算输赢
                        if (prevPkPlanModel != null && SimulationPlanConfig.isBet) { //下注计划存在,并且已经下注状态
                            if (isWin) {//赢了计算
                                SimulationPlanConfig.wallet += (int) (SimulationPlanConfig.bet.doubleValue()/5 * 9.9);
                                SimulationPlanConfig.singleScore += (int) (SimulationPlanConfig.bet.doubleValue()/5 * 9.9);
                               /* if (SimulationPlanConfig.wrongCount == 4) {
                                    SimulationPlanConfig.gameNums += 3;
                                }*/
                                if (SimulationPlanConfig.wrongCount == 5) {
                                    SimulationPlanConfig.gameIndex -= 3;
                                }
                                if (SimulationPlanConfig.wrongCount == 6) {
                                    SimulationPlanConfig.gameIndex -= 7;
                                }
                                SimulationPlanConfig.wrongCount = 0;
                                SimulationPlanConfig.gameIndex++; //游戏局数+1
                                if (SimulationPlanConfig.gameIndex > SimulationPlanConfig.gameNums) {
                                    SimulationPlanConfig.isAllowBet = false;
                                    SimulationPlanConfig.gameIndex = 0;
                                }
                            } else {//输了
                                SimulationPlanConfig.wrongCount++;
                                if (SimulationPlanConfig.wrongCount >= 7 || SimulationPlanConfig.singleScore == 0) {
                                    //SimulationPlanConfig.isAllowBet = false;
                                    SimulationPlanConfig.wrongCount = 0;
                                    if (SimulationPlanConfig.gameIndex < 0) {
                                        SimulationPlanConfig.winRate = 40;
                                    }
                                    SimulationPlanConfig.reInitSingleScore();
                                    if (SimulationPlanConfig.winRate < 45) {
                                        SimulationPlanConfig.gameIndex = -30;
                                    } else {
                                        SimulationPlanConfig.gameIndex = -15;
                                    }
                                }
                            }
                        }
                    } else {//没有达到策略下注要求
                        if (prevPkPlanModel != null) { //没有达到下注要求并且本局赢了
                            if (isWin) {
                                if (SimulationPlanConfig.wrongCount >= 6) {
                                    SimulationPlanConfig.reInitSingleScore();
                                    //TODO 检测连错前30局 胜率
                                    double winRate = pkPlanModelDao.getWinRate(SimulationPlanConfig.wrongCount+1,SimulationPlanConfig.gameNums);
                                    SimulationPlanConfig.winRate = winRate;
                                    if (winRate < 56 && winRate >= 45) {
                                        SimulationPlanConfig.gameIndex = 0;
                                    } else if (winRate > 56) {
                                        SimulationPlanConfig.gameIndex = 20;
                                    } else {
                                        SimulationPlanConfig.gameIndex = 0;
                                    }
                                    SimulationPlanConfig.isAllowBet = true;

                                } else {
                                    SimulationPlanConfig.isAllowBet = false;
                                }
                                SimulationPlanConfig.wrongCount = 0;
                            } else {
                                SimulationPlanConfig.wrongCount++;
                            }
                        }
                    }
                } else {
                    SimulationPlanConfig.wrongCount = 0;
                    SimulationPlanConfig.isAllowBet = false;
                }
                prevPkPlanModel.setWinPlan(isWin);
            }
        }
        int count = lotteryDao.lotteryCount(1025L);
        if (count > 25) {//开始生成计划
            for (int i = 1; i <= 1; i++) {
                PkPlanModel pkPlanModel = genPkPlan(i);
            }
            //计划生成完毕，游戏打开，允许下注。
            SimulationPlanConfig.isBet = false;
        }
        prveLottery = lottery;
    }



    /**
     * 生成计划
     *
     * @param type
     */
    @Override
    public PkPlanModel genPkPlan(Integer type) {
        Integer[] nums = new Integer[]{0,1, 2, 3, 4, 5, 6, 7, 8, 9};
        //Integer type = 1;//冠军计划
        List<Map<String, Object>> numFrequency = new ArrayList<>();
        numFrequency = pkDetailDao.numFrequencyList(LOTTERY_ID, NUM_SIZE, nums, type);  //假设可以查询出来了。
        //LOGGER.info("frequency:" + JSON.toJSONString(numFrequency));
        //生成计划。
        List<Map<String, Object>> movingAverage = movingAverage(numFrequency);

        PkPlanModel pkPlanModel = chooseNum(movingAverage, numFrequency, type);

        LOGGER.info("plan:" + JSON.toJSONString(pkPlanModel));
        return pkPlanModel;
    }



    /**
     * @param mapList      //移动平均线
     * @param numFrequency 本期每个号码20期内出现频率
     * @param type         冠军/亚军...
     * @return
     */
    public PkPlanModel chooseNum(List<Map<String, Object>> mapList, List<Map<String, Object>> numFrequency, Integer type) {
        Map<String, Object> avgMap = mapList.get(0);
        Map<String, Object> frequencyMap = numFrequency.get(0);
        //System.out.println(avgMap.get("issue").equals(frequencyMap.get("issue")));
        Lottery lottery = lotteryDao.getLottery(LOTTERY_ID, (Long) avgMap.get("issue"));
        String[] cars = lottery.getOpenNum().split(",");
        //List<Integer> nums = new ArrayList<>();
        Map<String, Object> nums = new HashMap<>();    //金叉上面的号码 其次
        Map<String, Object> goldenCrosses = new HashMap<>();  //金叉  首选
        Map<String, Object> residueNums = new HashMap<>();   //最后选
        for (String key :
                avgMap.keySet()) {
            if (!key.equals("issue")) {
                //将号码加入准计划,并在备选号码中移除该号码
                String openNum = cars[type - 1];//上一期开奖号码。
                //TODO 目前还没有不选择上期开奖开出来号码， 验证代码，暂时无效。
                if ((double) avgMap.get(key) < Integer.valueOf(frequencyMap.get(key).toString())) {
                    nums.put(key, Integer.valueOf(frequencyMap.get(key).toString()).intValue() + (double) avgMap.get(key));
                    //frequencyMap.remove(key);
                    continue;
                }
                if (isGoldenCross(mapList, numFrequency, key)) {
                    goldenCrosses.put(key, Integer.valueOf(frequencyMap.get(key).toString()));
                    //frequencyMap.remove(key);
                    continue;
                }
                if (isDeathCross(mapList, numFrequency, key,3)) {//死叉进入代码块，死叉： 如果连续n局平均值等于自己的值，第四局平局值低于自己的值那么僵设定为死叉。
                    LOGGER.info("死叉：" + key + ",avg-value:" + avgMap.get(key) + ", count-value:" + frequencyMap.get(key));
                    //frequencyMap.remove(key);
                    continue;
                }
                Double value = Integer.valueOf(frequencyMap.get(key).toString()) + Integer.valueOf(frequencyMap.get(key).toString()) - (double) avgMap.get(key);
                residueNums.put(key, value);
            }
        }
        Integer[] chooseNums = new Integer[5];
        //初始化数据
        //选择号码
        if (nums.size() > 5) {
            //排序
            nums = MapUtile.sortMapByValue(nums, (o1, o2) -> {
                return compare(o1, o2);
            });
            int i = 0;
            int index = 0;
            for (String num :
                    nums.keySet()) {
                if (!num.equals("issue")) {
                    if (i >= 1 && index < 5) {
                        chooseNums[index] = Integer.valueOf(num);
                        index++;
                    }
                    i++;
                }
            }
        } else if (nums.size() < 5) {
            //排序剩余号码，备选择。
            residueNums = MapUtile.sortMapByValue(residueNums, (o1, o2) -> {
                return compare(o1, o2);
            });
            int i = 0;
            int index = 0;

            for (String num :
                    nums.keySet()) {
                LOGGER.info("金叉线上：" + num + ",avg-value:" + avgMap.get(num) + ", count-value:" + frequencyMap.get(num));
                if (index < 5 && Integer.valueOf(frequencyMap.get(num).toString()) <= 5) {
                    chooseNums[index] = Integer.valueOf(num);
                    index++;
                }
            }

            for (String num :
                    goldenCrosses.keySet()) {
                LOGGER.info("金叉：" + num + ",avg-value:" + avgMap.get(num) + ", count-value:" + frequencyMap.get(num));
                if (index < 5 && Integer.valueOf(frequencyMap.get(num).toString()) < 5) {
                    chooseNums[index] = Integer.valueOf(num);
                    index++;
                }
            }
            for (String num :
                    residueNums.keySet()) {
                LOGGER.info("备选号码：" + num + ",avg-value:" + avgMap.get(num) + ", count-value:" + frequencyMap.get(num));
                if (!num.equals("issue")) {
                    if (i == 0 && Integer.valueOf(frequencyMap.get(num).toString()) < 5
                            && Double.valueOf(avgMap.get(num).toString()) <= Double.valueOf(frequencyMap.get(num).toString())) {
                        if (index < 5) {
                            chooseNums[index] = Integer.valueOf(num);
                            index++;
                        }
                    } else if (i >= 1 && index < 5) {
                        chooseNums[index] = Integer.valueOf(num);
                        index++;
                    }
                    i++;
                }
            }
        } else {//nums.size() == 5
            int index = 0;
            for (String num :
                    nums.keySet()) {
                if (!num.equals("issue")) {
                    chooseNums[index] = Integer.valueOf(num);
                    index++;
                }
            }
        }
        //排序号码
        chooseNums = sort(chooseNums);
        PkPlanModel pkPlanModel = new PkPlanModel(Long.valueOf(frequencyMap.get("issue").toString())+1,LOTTERY_ID,chooseNums,new Date(),type);
        LotteryConfig.pkPlanModels[type] = pkPlanModel;
        return pkPlanModel;
    }

    private boolean isGoldenCross(List<Map<String,Object>> mapList, List<Map<String,Object>> numFrequency, String key) {
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> avg = mapList.get(i);
            Map<String, Object> frequency = numFrequency.get(i);
            if (i == 0 && Double.valueOf(avg.get(key).toString()).doubleValue() != Double.valueOf(frequency.get(key).toString()).doubleValue()) {
                return false;
            }
            if (Double.valueOf(avg.get(key).toString()).doubleValue()==Double.valueOf(frequency.get(key).toString()).doubleValue()) {
                continue;
            }
            if (Double.valueOf(avg.get(key).toString()) > Double.valueOf(frequency.get(key).toString())&&
                    Double.valueOf(mapList.get(i-1).get(key).toString()) >= Double.valueOf(mapList.get(i).get(key).toString())) {
                if ( i > 0 ) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isDeathCross(List<Map<String,Object>> mapList, List<Map<String,Object>> numFrequency, String key, int n) {
        for (int i = 0; i < mapList.size(); i++) {
            Map<String, Object> avg = mapList.get(i);
            Map<String, Object> frequency = numFrequency.get(i);
            if (i == 0 && Double.valueOf(avg.get(key).toString()).doubleValue() != Double.valueOf(frequency.get(key).toString()).doubleValue()) {
                return false;
            }
            if (Double.valueOf(avg.get(key).toString()).doubleValue()==Double.valueOf(frequency.get(key).toString()).doubleValue()) {
                continue;
            }
            if (Double.valueOf(avg.get(key).toString()) < Double.valueOf(frequency.get(key).toString())) {
                if (i > 0 && i <= n) {
                    return true;
                }
            }
        }
        return false;

    }

    public Integer[] sort(Integer[] a) {

        List<Integer> list = Arrays.asList(a);
        Collections.sort(list, (o1, o2) -> {
            if (o1 > o2) {
                return 1;
            } else if (o1 < o2) {
                return -1;
            } else {
                return 0;
            }
        });
        a = list.toArray(a);
        return a;
    }


    /**
     * 数字 排序
     *
     * @param o1
     * @param o2
     * @return
     */
    public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
        /*double d1 = Double.valueOf(o1.getValue().toString()).doubleValue();
        double d2 = 0l;*/
        if (Double.valueOf(o1.getValue().toString()).doubleValue() < Double.valueOf(o2.getValue().toString()).doubleValue()) {
            return 1;
        } else if (Double.valueOf(o1.getValue().toString()).doubleValue() > Double.valueOf(o2.getValue().toString()).doubleValue()) {
            return -1;
        } else {
            return 0;
        }
    }

    private List<Map<String, Object>> movingAverage(List<Map<String, Object>> numFrequency) {
        List<Map<String, Object>> movingAverage = new ArrayList<>();
        for (int i = 0; i <= numFrequency.size() - 4; i++) {
            Map<String, Object> average = new HashMap<>();
            average.put("issue", numFrequency.get(i).get("issue"));
            int k = i;
            int[] frequencySum = new int[11];
            //计算n个数字的和
            for (int j = i; j < i + 4; j++) {
                Map<String, Object> map = numFrequency.get(j);
                for (String key :
                        map.keySet()) {
                    if (!key.equals("issue")) {
                        frequencySum[Integer.valueOf(key)] += Integer.valueOf(map.get(key).toString());
                    }
                }
            }
            //计算平局数
            for (int j = 0; j < 10; j++) {
                DecimalFormat df = new DecimalFormat("#.00");
                Double avg = Double.valueOf(df.format(frequencySum[j] / 4.0));
                average.put(String.valueOf(j), avg);
            }
            movingAverage.add(average);
        }
        return movingAverage;
    }


}
